1 /* ====================================================================
2 * Bigyo Software License, version 1.1
3 *
4 * Copyright (c) 2004, Zsombor Gegesy. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 *
17 * 3. Neither the name of the Bigyo Group nor the name "Bigyo" nor
18 * the names of its contributors may be used to endorse or promote
19 * products derived from this software without specific prior
20 * written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 *
35 * ====================================================================
36 */
37
38 package net.sf.bigyo.container.ant;
39
40 import java.io.BufferedWriter;
41 import java.io.File;
42 import java.io.FileWriter;
43 import java.io.IOException;
44 import java.util.ArrayList;
45 import java.util.Iterator;
46 import java.util.List;
47 import java.util.Map;
48 import java.util.Properties;
49
50 import net.sf.bigyo.api.ContainerException;
51 import net.sf.bigyo.container.ClassDependency;
52 import net.sf.bigyo.container.ComponentDescription;
53 import net.sf.bigyo.container.Kernel;
54 import net.sf.bigyo.container.Main;
55 import net.sf.bigyo.container.api.Constants;
56
57 import org.apache.avalon.fortress.util.dag.CyclicDependencyException;
58 import org.apache.log4j.BasicConfigurator;
59 import org.apache.tools.ant.BuildException;
60 import org.apache.velocity.Template;
61 import org.apache.velocity.VelocityContext;
62 import org.apache.velocity.app.VelocityEngine;
63
64 import com.thoughtworks.qdox.ant.AbstractQdoxTask;
65 import com.thoughtworks.qdox.model.AbstractJavaEntity;
66 import com.thoughtworks.qdox.model.DocletTag;
67 import com.thoughtworks.qdox.model.JavaClass;
68 import com.thoughtworks.qdox.model.JavaMethod;
69 import com.thoughtworks.qdox.model.JavaParameter;
70 import com.thoughtworks.qdox.model.Type;
71
72 /***
73 * @author zsombor
74 *
75 * Created at 20:02:11 net.sf.bigyo.container.ant.RegistryGenerator
76 * Created on 2004.09.19.
77 *
78 */
79 public class RegistryGenerator extends AbstractQdoxTask {
80
81 Main main;
82
83 String registryPath;
84
85 File outputDir;
86
87 boolean verbose = false;
88
89 Template mbeanImplTemplate;
90 Template mbeanTemplate;
91 Template beanWrapperTemplate;
92 Template factoryTemplate;
93 Template mbeanDescriptorTemplate;
94
95 Template pmMXTemplate;
96
97 boolean generateSource = false;
98
99 boolean generatePMX = false;
100
101 String rootRegistry = null;
102
103 /*
104 * (non-Javadoc)
105 *
106 * @see com.thoughtworks.qdox.ant.AbstractQdoxTask#execute()
107 */
108 public void execute() throws BuildException {
109 BasicConfigurator.configure();
110
111 generateSource = outputDir != null;
112
113 if (generateSource) {
114 log("source generating to " + outputDir);
115 VelocityEngine ve = new VelocityEngine();
116
117 try {
118 Properties prop = new Properties();
119 prop.setProperty("resource.loader", "classpath");
120 prop.setProperty("classpath.resource.loader.class",
121 "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
122
123 ve.init(prop);
124 mbeanTemplate = ve.getTemplate("net/sf/bigyo/container/ant/mbean.vm");
125 beanWrapperTemplate = ve.getTemplate("net/sf/bigyo/container/ant/beanwrapper.vm");
126 mbeanImplTemplate = ve.getTemplate("net/sf/bigyo/container/ant/mbeanimpl.vm");
127 factoryTemplate = ve.getTemplate("net/sf/bigyo/container/ant/factory.vm");
128 mbeanDescriptorTemplate = ve.getTemplate("net/sf/bigyo/container/ant/mbeandescriptor.vm");
129 pmMXTemplate = ve.getTemplate("net/sf/bigyo/container/ant/mxtemplate.vm");
130
131
132 } catch (Exception e) {
133 e.printStackTrace();
134 throw new BuildException("Exception:" + e.getMessage(), e);
135 }
136 } else {
137 log("source not generated");
138 }
139
140 main = new Main();
141
142 super.execute();
143
144 log("create registry at " + registryPath);
145
146 for (int i = 0; i < this.allClasses.size(); i++) {
147 JavaClass jc = (JavaClass) allClasses.get(i);
148 DocletTag tag = jc.getTagByName("bigyo-component");
149 if (tag != null) {
150 parseClass(jc, tag);
151 }
152 }
153
154 try {
155 if (rootRegistry != null)
156 main.loadComponentRegistry(Kernel.createReader(rootRegistry));
157 main.getRegistry().validateRegistry();
158 main.getRegistry().storeRegistry(registryPath);
159 log("finished.");
160 } catch (CyclicDependencyException e) {
161 e.printStackTrace();
162 throw new BuildException("Cyclic dependency error:" + e.getMessage(), e);
163 } catch (ContainerException e) {
164 e.printStackTrace();
165 throw new BuildException("Container exception:" + e.getMessage(), e);
166 } catch (IOException e) {
167 e.printStackTrace();
168 throw new BuildException("IO exception:" + e.getMessage(), e);
169
170 }
171
172 }
173
174 public void setRootRegistry(String path) {
175 log("registry " + path + " added");
176 rootRegistry = path;
177 }
178
179
180 class ComponentInfo {
181 JavaClass jc;
182 ComponentDescription cd;
183 List publishedMethods;
184
185 /***
186 * @param jc
187 * @param cd
188 */
189 public ComponentInfo(JavaClass jc, ComponentDescription cd) {
190 super();
191 publishedMethods = new ArrayList();
192 this.jc = jc;
193 this.cd = cd;
194 }
195
196 public void addToPublish(JavaMethod method) {
197 publishedMethods.add(method);
198 }
199
200 /***
201 * @return Returns the publishedMethods.
202 */
203 public List getPublishedMethods() {
204 return publishedMethods;
205 }
206
207 /***
208 * @return Returns the JavaClass .
209 */
210 public JavaClass getJavaClass() {
211 return jc;
212 }
213
214 /***
215 * @return Returns the ComponentDescription.
216 */
217 public ComponentDescription getComponentDescription() {
218 return cd;
219 }
220 }
221
222 /***
223 * @param jc
224 * @param tag
225 */
226 private void parseClass(JavaClass jc, DocletTag tag) {
227 String componentName = tag.getValue();
228 String type = getValue(jc, "bigyo-type", "singleton");
229 log("found component : " + jc.getFullyQualifiedName());
230 log(" component name:" + componentName);
231 if (componentName == null || "".equals(componentName.trim()))
232 throw new BuildException("component name is not specified in: " + jc.getFullyQualifiedName()
233 + ", missing tag: @bigyo-component my-component");
234 if (verbose)
235 log(" type: " + type);
236
237 ComponentDescription cd = new ComponentDescription(componentName, jc.getFullyQualifiedName(), null, type);
238
239 ComponentInfo ci = new ComponentInfo(jc, cd);
240
241 DocletTag[] provides = jc.getTagsByName("bigyo-provide");
242 for (int j = 0; j < provides.length; j++) {
243 if (verbose)
244 log(" provides:" + provides[j].getValue());
245 cd.addProvideAlias(provides[j].getValue());
246 }
247
248 DocletTag[] depends = jc.getTagsByName("bigyo-after");
249 for (int j = 0; j < depends.length; j++) {
250 if (verbose)
251 log(" after :" + depends[j].getValue());
252 cd.addDepend(depends[j].getValue(), ClassDependency.AFTER);
253 }
254
255 depends = jc.getTagsByName("bigyo-before");
256 for (int j = 0; j < depends.length; j++) {
257 if (verbose)
258 log(" before :" + depends[j].getValue());
259 cd.addDepend(depends[j].getValue(), ClassDependency.BEFORE);
260 }
261
262 depends = jc.getTagsByName("bigyo-depend");
263 for (int j = 0; j < depends.length; j++) {
264 if (verbose)
265 log(" depend :" + depends[j].getValue());
266 cd.addDepend(depends[j].getValue());
267 }
268
269 DocletTag[] alias = jc.getTagsByName("bigyo-alias");
270 for (int i=0;i<alias.length;i++) {
271 Map map = alias[i].getNamedParameterMap();
272
273 for (Iterator keys= map.keySet().iterator();keys.hasNext();) {
274 String key = (String) keys.next();
275 String value = ((String) map.get(key)).replace('-','$');
276 if (verbose)
277 log(" alias :" + key+" -> "+value);
278 cd.setClassShortcut(key,value);
279 }
280 }
281
282 JavaClass configClass = null;
283
284 //System.out.println("methods:"+methods.length);
285 configClass = parseMethods(jc, ci);
286 JavaClass sup = jc.getSuperJavaClass();
287 while (sup != null) {
288 log("parse super class:" + sup.getName());
289 parseMethods(sup, ci);
290 sup = sup.getSuperJavaClass();
291 }
292 createMBean(configClass, ci);
293 main.getRegistry().addComponentDescription(cd);
294
295 }
296
297 /***
298 * @param jc
299 * @param ci
300 * @param configClass
301 * @return
302 */
303 private JavaClass parseMethods(JavaClass jc, ComponentInfo ci) {
304 JavaClass configClass = null;
305 JavaMethod[] methods = jc.getMethods();
306 for (int j = 0; j < methods.length; j++) {
307 JavaMethod m = methods[j];
308
309 Type t = parseMethod(ci, m);
310 if (t != null)
311 configClass = t.getJavaClass();
312 }
313 return configClass;
314 }
315
316
317 /***
318 * @param generatePMX The generatePMX to set.
319 */
320 public void setPMX(boolean generatePMX) {
321 this.generatePMX = generatePMX;
322 }
323 /***
324 * @param cd
325 * @param m
326 */
327 private Type parseMethod(ComponentInfo ci, JavaMethod m) {
328 ComponentDescription cd = ci.getComponentDescription();
329 if (verbose)
330 log("method:" + m.getName() + " constructor:" + m.isConstructor());
331 Type configType = null;
332 if (m.isConstructor() && (cd.getConfigClass() == null)) {
333 if (getValue(m, "bigyo-constructor") != null) {
334 JavaParameter[] params = m.getParameters();
335 if (params.length > 0) {
336 configType = params[0].getType();
337 if (verbose)
338 log(" config class:" + configType.getValue());
339 cd.setConfigClass(configType.getValue());
340 } else {
341 if (verbose)
342 log(" no-op constructor");
343 }
344 }
345 } else {
346 String value = getValue(m, "bigyo-depend");
347 if (value != null) {
348 if (verbose)
349 log(" dependency on:" + value + " [" + m.getName() + ']');
350 cd.addDependSetter(value, m.getName());
351 }
352 value = getValue(m, "bigyo-optional");
353 if (value != null) {
354 if (verbose)
355 log(" optional dependency on:" + value + " [" + m.getName() + ']');
356 cd.addOptionalDependSetter(value, m.getName());
357 }
358 if (hasValue(m, "bigyo-start") && cd.getStart() == null) {
359 if (verbose)
360 log(" start method:" + m.getName());
361 cd.setStart(m.getName());
362 }
363 if (hasValue(m, "bigyo-stop") && cd.getStop() == null) {
364 if (verbose)
365 log(" stop method:" + m.getName());
366 cd.setStop(m.getName());
367 }
368 if (hasValue(m, "bigyo-publish")) {
369 if (verbose)
370 log(" published method:" + m.getName());
371 ci.addToPublish(m);
372 }
373 }
374 return configType;
375 }
376
377 private String getValue(AbstractJavaEntity jc, String name) {
378 return getValue(jc, name, null);
379 }
380
381 private boolean hasValue(AbstractJavaEntity jc, String name) {
382 DocletTag tag = jc.getTagByName(name);
383 /*
384 * if (verbose) log("tag:"+tag+" "+jc+"-"+name);
385 */
386 return tag != null;
387 }
388
389 private String getValue(AbstractJavaEntity jc, String name, String defValue) {
390 DocletTag tag = jc.getTagByName(name);
391 if (tag != null)
392 return tag.getValue();
393 return defValue;
394 }
395
396 /***
397 * @param registryPath
398 * The registryPath to set.
399 */
400 public void setRegistryPath(String registryPath) {
401 this.registryPath = registryPath;
402 }
403
404 /***
405 * @param verbose
406 * The verbose to set.
407 */
408 public void setVerbose(boolean verbose) {
409 this.verbose = verbose;
410 }
411
412 /***
413 * @param outputDir
414 * The outputDir to set.
415 */
416 public void setOutputDirectory(File outputDir) {
417 this.outputDir = outputDir;
418 }
419
420 void createMBean(JavaClass jc, ComponentInfo ci) {
421 JavaClass serviceClass = ci.getJavaClass();
422
423 if (!generateSource)
424 return;
425 VelocityContext context = new VelocityContext();
426 log("create mbean for " + serviceClass.getPackage() + ':' + serviceClass.getName());
427 if (jc != null) {
428 context.put("javaclass", jc);
429 context.put("attributes", jc.getBeanProperties());
430 context.put("methods",jc.getMethods(false));
431 context.put("wrapperName", Constants.getWrapperName(jc.getName()));
432 context.put("factoryName", Constants.getFactoryName(jc.getName()));
433 }
434 log("service class:" + serviceClass.getName());
435 context.put("description", ci.getComponentDescription());
436 context.put("mbeanName", Constants.getMBeanName(serviceClass.getName()));
437 context.put("mbeanImplName", Constants.getMBeanImplName(serviceClass.getName()));
438 context.put("mbeanDescriptor", Constants.getMBeanDescriptor(serviceClass.getName()));
439 context.put("serviceclass", serviceClass);
440 context.put("mxClass",Constants.getPMX(serviceClass.getName()));
441
442 context.put("publish", ci.getPublishedMethods());
443
444 try {
445 // create necessary directories
446 File serviceOutput = new File(outputDir, serviceClass.getPackage().replace('.', File.separatorChar));
447 serviceOutput.mkdirs();
448
449 // create MBeanImpl class
450 mergeTemplate(context, mbeanImplTemplate, serviceOutput, Constants.getMBeanImplName(serviceClass.getName())
451 + ".java");
452
453 // create MBean interface
454 mergeTemplate(context, mbeanTemplate, serviceOutput, Constants.getMBeanName(serviceClass.getName())
455 + ".java");
456
457 // create MBean Descriptor
458 mergeTemplate(context, mbeanDescriptorTemplate, serviceOutput, Constants.getMBeanDescriptor(serviceClass
459 .getName())
460 + ".java");
461
462 if (generatePMX) {
463 mergeTemplate(context, pmMXTemplate, serviceOutput, Constants.getPMX(serviceClass.getName())+".java");
464 }
465 // create necessary directories
466 if (jc != null) {
467 File output = new File(outputDir, jc.getPackage().replace('.', File.separatorChar));
468 output.mkdirs();
469 // create Bean wrapper
470 mergeTemplate(context, beanWrapperTemplate, output, Constants.getWrapperName(jc.getName()) + ".java");
471 }
472 // create Bean wrapper
473 //if (!"singleton".equals(cd.getType())) {
474 //mergeTemplate(context,factoryTemplate,output,jc.getName()+"Factory.java");
475 //}
476
477 } catch (Exception rnf) {
478 rnf.printStackTrace();
479 throw new RuntimeException("Exception:" + rnf.getMessage(), rnf);
480 }
481
482 }
483
484 void mergeTemplate(VelocityContext context, Template t, File output, String fileName) throws Exception {
485 BufferedWriter w = new BufferedWriter(new FileWriter(new File(output, fileName)));
486 t.merge(context, w);
487 w.close();
488
489 }
490
491 }
This page was automatically generated by Maven